﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EzyGoEzySystem.Models;

namespace EzyGoEzySystem.Services.DataStructures
{
    public class Graph
    {
        public int NumberOfBusStop { get; set; }
        public Node[] BusStop { get; set; }

        public Graph(EzyGoEzyDBContext dbContext)
        {
            NumberOfBusStop = NumBusStop(dbContext);
            BuildGraph(dbContext);
        }
        public void BuildGraph(EzyGoEzyDBContext dbContext)
        {
            BusStop = new Node[NumberOfBusStop];

            //initialize BusStop array
            int index = 0;
            foreach (var busStop in dbContext.BusStop)
            {
                string name = busStop.Name;
                double h = StraightLine(name, dbContext);
                BusStop[index] = new Node(name, h, dbContext);
                index++;
            }

            //route information
            List<Route> routes = BusConnection(dbContext);
            //traverse route information
            index = 0;
            foreach (var route in routes)
            {
                BusStop[IndexOf(BusStop, route.StartBusStopID, dbContext)].Connection.
                    Add(new Connection(IndexOf(BusStop, route.StartBusStopID, dbContext),
                        IndexOf(BusStop, route.EndBusStopID, dbContext), route.DistanceCost));
            }
           
        }

        #region Helper Method

        //return number of Bus Stop in database
        public int NumBusStop(EzyGoEzyDBContext dbContext)
        {
            int number;
            var entry = from busStopEntry in dbContext.BusStop
                        select busStopEntry;
            number = entry.Count();
            return number;
        }

        //method will return the bus name when enter bus ID
        public string NameBusStop(int busStopID, EzyGoEzyDBContext dbContext)
        {
            var entry = from busStopEntry in dbContext.BusStop
                        where busStopEntry.ID == busStopID
                        select busStopEntry;
            var firstEntry = entry.First();
            return firstEntry.Name;
        }

        //method will return bus stopID when enter busName
        public int IDBusStop(string busName, EzyGoEzyDBContext dbContext)
        {
            var entry = from busStopEntry in dbContext.BusStop
                        where busStopEntry.Name == busName
                        select busStopEntry;
            var firstEntry = entry.First();
            return firstEntry.ID;
        }

        //method will return busName when enter busID
        public string NameBus(int busID, EzyGoEzyDBContext dbContext)
        {
            var entry = from busEntry in dbContext.Bus
                        where busEntry.ID == busID
                        select busEntry;
            var firstEntry = entry.First();
            return firstEntry.Name;
        }

        //this method will return a list of bus stop connection
        public List<Route> BusConnection(EzyGoEzyDBContext dbContext)
        {
            var entry = from routeEntry in dbContext.Route
                        select routeEntry;
            return entry.ToList<Route>();
        }

        //method to return an index of a elemnent specified
        public int IndexOf(Node[] array, string name)
        {
            int index = 0;
            foreach (var element in array)
            {
                if (element.BusStopName == name)
                    return index;
                else
                    index++;
            }
            return -1; //if can not file the name of BusStop in array
        }

        //method to return an index of BusStop ID specified
        public int IndexOf(Node[] array, int id, EzyGoEzyDBContext dbContext)
        {
            string name = NameBusStop(id, dbContext);
            return IndexOf(array, name);
        }

        //method return Node of BusStop
        public Node FindNode(string busStopName)
        {
            foreach (var busStopNode in BusStop)
            {
                if (busStopNode.BusStopName == busStopName)
                    return busStopNode;
            }
            return null;
        }

        //method to find straightLine distance of a Bus Stop
        public double StraightLine(string busStopName, EzyGoEzyDBContext dbContext)
        {
            int busStopID = IDBusStop(busStopName, dbContext);
            var entry = from straightEntry in dbContext.StraightLineDistance
                        where straightEntry.StartBusStopID == busStopID
                        select straightEntry;
            var firstEntry = entry.First();
            return firstEntry.Distance;
        }

        #endregion
    }
}